import cv2
import pickle

'''
pickle 模块实现了一种算法.用于序列化和反序列化，作用是将一个对象转换为字节流，这样就可以保存在文件中或者通过网络传输。
好处是可以保存对象的状态，下次使用时直接加载，而不需要重新计算。
Serialize_data = pickle.dump(data)  # 序列化
Deserialize_data = pickle.load(Serialize_data) # 反序列化
'''


rectW,rectH=107,48

try:
    with open('CarParkPos','rb') as f:
        posList=pickle.load(f)
except:
    # 使用一个空列表
    posList=[]

def mouseClick(events,x,y,flags,params):
    # 鼠标的事件，鼠标的坐标，鼠标的标志，和鼠标的参数,eg:(0 333 13 0 None)
    print(events,x,y,flags,params)
    global posList
    # 事件是按下鼠标左键的时候，添加一个矩形左上角的坐标
    if events==cv2.EVENT_LBUTTONDOWN:
        posList.append((x,y))
    if events==cv2.EVENT_RBUTTONDOWN:
        '''
        这行代码是 Python 中的一个 for 循环，它遍历 posList 列表。
        enumerate() 函数用于将一个可遍历的数据对象（如列表、元组或字符串）组合为一个索引序列，同时列出数据和数据下标，
        一般用在 for 循环当中。在这个循环中，i 是当前元素的索引（从0开始），pos 是 posList 中的当前元素。
        例如，如果 posList 是 [(1, 2), (3, 4), (5, 6)]，那么在第一次循环中，i 会是 0，pos 会是 (1, 2)；在第二次循环中，
        i 会是 1，pos 会是 (3, 4)，以此类推。
        '''
        # enumerate 列举，返回的是一个元组，i是索引，pos是元组。enumerate(posList)返回的是一个元组,那么pos是enumerate(posList)的元组的元素
        for i,pos in enumerate(posList):
            # pos是一个元组，元组的第一个元素是x坐标，第二个元素是y坐标
            x1,y1=pos
            # 如果鼠标右键点击的位置在矩形内，就删除这个矩形
            if x1<x<x1+rectW and y1<y<y1+rectH:
                # 这里的psList是一个列表，列表的pop方法是删除列表中的一个元素，参数是元素的索引
                posList.pop(i)
    with open('CarParkPos','wb') as f:
        pickle.dump(posList,f)
    
            

while True:
    img=cv2.imread("Car-Parking-Space-Counter-Detector-main\\img.png")
    for pos in posList: 
        # rectangle 画矩形，参数是图片，左上角坐标，右下角坐标，绘画颜色，线宽
        cv2.rectangle(img,pos,(pos[0]+rectW,pos[1]+rectH),(0,0,255),2)
    
    cv2.imshow("Image",img)
    # setMouseCallback 鼠标回调，当鼠标点击的时候，调用mouseClick函数，传递的参数是鼠标的事件，鼠标的坐标，鼠标的标志，和鼠标的参数
    cv2.setMouseCallback("Image",mouseClick)
    if cv2.waitKey(1) & 0xFF==ord('q'): 
        break
